package com.bt.springboot.common.util;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;
import java.util.Random;
import java.util.zip.Deflater;

@Slf4j
public class IMUtil {

	private IMUtil() {
	}

	private static Random random;

	public static final String USER_ID = "jhn";

	public static final int SDK_APP_ID = 1400617058;

	public static final int EXPIRE_TIME = 315360000;

	public static final String SECRET_KEY = "2a266c332ea8cfe00d83d9f4c973b04bde6baa124680c8f357f7e24f03070a0e";

	/**
	 * 导入单个帐号
	 */
	public static final String ACCOUNT_IMPORT = "https://console.tim.qq.com/v4/im_open_login_svc/account_import";

	/**
	 * 导入多个帐号
	 */
	public static final String MULTIACCOUNT_IMPORT = "https://console.tim.qq.com/v4/im_open_login_svc/multiaccount_import";

	/**
	 * 发送消息
	 */
	public static final String SEND_MESSAGE = "https://console.tim.qq.com/v4/openim/sendmsg";

	/**
	 * 向多个目标账号发送消息
	 */
	public static final String BATCH_SEND_MESSAGE = "https://console.tim.qq.com/v4/openim/batchsendmsg";

	/**
	 * 获取上线消息
	 */
	public static String getOnMsg(String name) {
		return "销售" + name + "当前已上线，请根据销售实际状况调整在线状态";
	}

	/**
	 * 获取离线消息
	 */
	public static String getDownMsg(String name) {
		return "销售" + name + "当前已离线，请根据销售实际状况调整在线状态";
	}






	/**
	 * 【功能说明】用于签发 TRTC 和 IM 服务中必须要使用的 UserSig 鉴权票据
	 * <p>
	 * 【参数说明】
	 * @param userid - 用户id，限制长度为32字节，只允许包含大小写英文字母（a-zA-Z）、数字（0-9）及下划线和连词符。
	 * @return usersig -生成的签名
	 */
	public static String genUserSig(String userid) {
		return genUserSig(userid, EXPIRE_TIME, null);
	}

	/**
	 * 【功能说明】用于签发 TRTC 和 IM 服务中必须要使用的 UserSig 鉴权票据
	 * <p>
	 * 【参数说明】
	 * @param userid - 用户id，限制长度为32字节，只允许包含大小写英文字母（a-zA-Z）、数字（0-9）及下划线和连词符。
	 * @param expire - UserSig 票据的过期时间，单位是秒，比如 86400 代表生成的 UserSig 票据在一天后就无法再使用了。
	 * @return usersig -生成的签名
	 */
	public static String genUserSig(String userid, long expire) {
		return genUserSig(userid, expire, null);
	}



	private static String genUserSig(String userid, long expire, byte[] userbuf) {

		long currTime = System.currentTimeMillis() / 1000;

		JSONObject sigDoc = new JSONObject();
		sigDoc.put("TLS.ver", "2.0");
		sigDoc.put("TLS.identifier", userid);
		sigDoc.put("TLS.sdkappid", SDK_APP_ID);
		sigDoc.put("TLS.expire", expire);
		sigDoc.put("TLS.time", currTime);

		String base64UserBuf = null;
		if (null != userbuf) {
			base64UserBuf = Base64.getEncoder().encodeToString(userbuf).replaceAll("\\s*", "");
			sigDoc.put("TLS.userbuf", base64UserBuf);
		}
		String sig = hmacsha256(userid, currTime, expire, base64UserBuf);
		if (sig.length() == 0) {
			return "";
		}
		sigDoc.put("TLS.sig", sig);
		Deflater compressor = new Deflater();
		compressor.setInput(sigDoc.toString().getBytes(StandardCharsets.UTF_8));
		compressor.finish();
		byte[] compressedBytes = new byte[2048];
		int compressedBytesLength = compressor.deflate(compressedBytes);
		compressor.end();
		return (new String(base64EncodeUrl(Arrays.copyOfRange(compressedBytes, 0, compressedBytesLength))))
				.replaceAll("\\s*", "");
	}

	private static byte[] base64EncodeUrl(byte[] input) {
		byte[] base64 = Base64.getEncoder().encode(input);
		for (int i = 0; i < base64.length; ++i)
			switch (base64[i]) {
			case '+':
				base64[i] = '*';
				break;
			case '/':
				base64[i] = '-';
				break;
			case '=':
				base64[i] = '_';
				break;
			default:
				break;
			}
		return base64;
	}

	private static String hmacsha256(String identifier, long currTime, long expire, String base64Userbuf) {
		String contentToBeSigned = "TLS.identifier:" + identifier + "\n" + "TLS.sdkappid:" + SDK_APP_ID + "\n"
				+ "TLS.time:" + currTime + "\n" + "TLS.expire:" + expire + "\n";
		if (null != base64Userbuf) {
			contentToBeSigned += "TLS.userbuf:" + base64Userbuf + "\n";
		}
		try {
			byte[] byteKey = SECRET_KEY.getBytes(StandardCharsets.UTF_8);
			Mac hmac = Mac.getInstance("HmacSHA256");
			SecretKeySpec keySpec = new SecretKeySpec(byteKey, "HmacSHA256");
			hmac.init(keySpec);
			byte[] byteSig = hmac.doFinal(contentToBeSigned.getBytes(StandardCharsets.UTF_8));
			return (Base64.getEncoder().encodeToString(byteSig)).replaceAll("\\s*", "");
		}
		catch (NoSuchAlgorithmException | InvalidKeyException e) {
			return "";
		}
	}

}
